﻿#region Usings

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Net;
using System.Reflection;
using iTunesLib;

#endregion

namespace iTunesArtworkApp.Core
{
    /// <summary>
    ///   Represents the iTunesWrapper Interface.
    /// </summary>
    public class iTunesWrapper : IiTunesWrapper
    {
        private const string AUDIOFILE = "AAC audio file";

        /// <summary>
        ///   Gets a list of albums that don't have associated album art work.
        /// </summary>
        /// <returns>A collection of albums</returns>
        public ICollection<Album> GetAlbums()
        {
            // We want a distinct list of albums to process
            // The hashset will remove the duplicates
            var albums = new HashSet<Album>(new AlbumComparer());

            var iTunesApp = new iTunesApp();
            var mainLibrary = iTunesApp.LibraryPlaylist;
           
            // Search for the Music Tracks
            // The mainLibrary contains music/videos and apps etc
            var musicTracks =
                mainLibrary.Tracks.Cast<IITTrack>().Where(x => x.KindAsString == AUDIOFILE);

            // Get the list of tracks that don't have any art work.
            var musicTracksMissingArt =
                musicTracks.Where(x => x.Artwork.Count == 0).OrderBy(x => x.Artist);

            foreach (IITTrack track in musicTracksMissingArt)
            {
                var album = new Album
                                {
                                    Id = track.trackID,
                                    AlbumName = track.Album, 
                                    Artist = track.Artist
                                };
                

                albums.Add(album);
            }

            return albums;
        }

        /// <summary>
        ///   Updates the Artwork on the Album.
        /// </summary>
        /// <param name = "album">The album to update</param>
        public void UpdateArtwork(ref Album album)
        {

            var iTunesApp = new iTunesApp();
            var mainLibrary = iTunesApp.LibraryPlaylist;

            // Get iTunes track that matches album 
            var albumId = album.Id;
            var tracks =
                mainLibrary.Tracks.Cast<IITTrack>().Where(x => x.trackID == albumId);
            if (tracks.Count() == 0)
                throw new ApplicationException(string.Format("Could not find album in itunes. {0} - {1}", album.Artist, album.AlbumName));
            var iTuneTrack = tracks.First();

            // download album image using http to isolated storage
            var imageFilePath = GetAlbumArtworkFile(album);
            
            // Update artwork in albums
            if (string.IsNullOrEmpty(imageFilePath))
                throw new ApplicationException(string.Format("Could not download album art. {0} - {1}", album.Artist, album.AlbumName));
            iTuneTrack.AddArtworkFromFile(imageFilePath);

            album.Artwork.HasArtwork = true;

            // clean up isolated storage
            CleanUpArtwork(imageFilePath);
        }

        /// <summary>
        /// Gets the album artwork file.
        /// </summary>
        /// <remarks>
        /// download album image using http to disk
        /// </remarks>
        /// <param name="album">The album.</param>
        private string GetAlbumArtworkFile(Album album)
        {
            if (album == null) throw new ArgumentNullException("album");
            if (album.Artwork.DownloadUrl == null) throw new ArgumentException(string.Format("Ablum {0} {1} has no download url",album.Artist, album.AlbumName));

            var client = new WebClient();
            var albumImageMemoryStream = new MemoryStream(client.DownloadData(album.Artwork.DownloadUrl));

            
            var fileName = string.Format("{0}-{1}.jpg", album.AlbumName, album.Id);
            String assembyPath = System.IO.Path.GetDirectoryName(
                                System.Reflection.Assembly.GetExecutingAssembly().Location);
            var filePath = Path.Combine(assembyPath, fileName);

            // delete if exists
            if (File.Exists(filePath))
                File.Delete(filePath);
           using (var writer = File.Create(filePath))
            {
                var data = albumImageMemoryStream.ToArray();
                writer.Write(data, 0, data.Length);
            }
            albumImageMemoryStream.Close();

            return filePath;
        }

        /// <summary>
        /// Cleans up artwork on disk
        ///  </summary>
        /// <param name="fileName">The fileName.</param>
        private void CleanUpArtwork(string fileName)
        {
            // delete if exists
            if (File.Exists(fileName))
                File.Delete(fileName);
        }

    } // end class
}